package com.mye.prometheusexportdcim.utils;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.crypto.digest.MD5;
import org.snmp4j.PDU;
import org.snmp4j.ScopedPDU;
import org.snmp4j.event.ResponseEvent;
import org.snmp4j.mp.SnmpConstants;
import org.snmp4j.smi.OID;
import org.snmp4j.smi.VariableBinding;

import java.util.List;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @author hch
 * @创建人 hch
 * @创建时间 2021/4/27 9:50
 * @描述 TODO
 * @版本 1.0.0
 */
public class SnmpUtil {


    private static final ConcurrentHashMap<String, Snmp4j> CONCURRENT_HASH_MAP = new ConcurrentHashMap<>();


    private static Snmp4j getSnmp(String addr, int version) {
        return CONCURRENT_HASH_MAP.computeIfAbsent(getKye(addr, version), k -> new Snmp4j(addr, version));
    }

    private static String getKye(String addr, int version) {
        MD5 md5 = MD5.create();
        return md5.digestHex(addr + "/" + version);
    }


    /**
     * @param udp                :     udp 地址
     * @param version            :     版本
     * @param type               :    udp 类型,
     * @param oids               :    oid 可以是多个
     * @param username           :    用户名
     * @param authWay            :    认证方式
     * @param authPassword       ：   认证密码
     * @param encryptionWay      ：    加密方式
     * @param encryptionPassword  ：   加密密码
     **/
    public static ResponseEvent sendMessage(String udp, int version, int type, List<String> oids, String username, String authWay, String authPassword, String encryptionWay, String encryptionPassword) {
        Snmp4j manager = getSnmp(udp, version);
        PDU pdu = getPdu(version, oids);
        if (pdu == null) {
            return null;
        }
        pdu.setType(type);
        return manager.sendMessage(pdu, udp, username, authWay, authPassword, encryptionWay, encryptionPassword);
    }

    private static PDU getPdu(int version, List<String> oids) {
        if (CollectionUtil.isEmpty(oids)) {
            return null;
        }
        PDU pdu;
        if (SnmpConstants.version3 == version) {
            pdu = new ScopedPDU();
        } else {
            pdu = new PDU();
        }
        List<VariableBinding> variableBindingList = oids.stream().filter(Objects::nonNull).map(s -> new VariableBinding(new OID(s))).distinct().collect(Collectors.toList());
        pdu.addAll(variableBindingList);
        return pdu;
    }

}
